package com.edu.chat.web.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.chat.web.common.enums.ResultCodeEnum;
import com.edu.chat.web.common.model.BizException;
import com.edu.chat.web.common.model.R;
import com.edu.chat.web.controller.vo.CategoryVO;
import com.edu.chat.web.covert.CategoryCovert;
import com.edu.chat.web.dto.ArticleDTO;
import com.edu.chat.web.dto.CategoryNodeDTO;
import com.edu.chat.web.dto.FileDTO;
import com.edu.chat.web.dto.LibraryTreeDTO;
import com.edu.chat.web.mapper.CsCategoriesMapper;
import com.edu.chat.web.model.CsCategories;
import com.edu.chat.web.service.CsArticleService;
import com.edu.chat.web.service.CsCategoriesService;
import com.edu.chat.web.service.CsFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @author 86177
 * @description 针对表【cs_categories(分类信息表)】的数据库操作Service实现
 * @createDate 2025-02-22 15:02:27
 */
@Service
@Slf4j
public class CsCategoriesServiceImpl extends ServiceImpl<CsCategoriesMapper, CsCategories> implements CsCategoriesService{

	@Autowired
	private CsFileService csFileService;

	@Autowired
	private CsArticleService csArticleService;

	@Override
	public R<Boolean> initRootCategory(Long libraryId) {
		log.info("initRootCategory libraryId:{}", libraryId);
		if(libraryId == null) {
			throw new BizException(ResultCodeEnum.PARAM_INVALID,"libraryId is null");
		}

		CsCategories csCategories = new CsCategories();
		csCategories.setLibraryId(libraryId);
		csCategories.setTitle("根目录");
		csCategories.setDescription("根目录");
		csCategories.setParentCategoryId(0L);
		save(csCategories);

		return R.status(true);
	}

	@Override
	public R<Boolean> createCategory(CategoryVO categoryVO) {

		if(categoryVO == null) {
			throw new BizException(ResultCodeEnum.PARAM_INVALID,"categoryVO is null");
		}

		//判断父级目录是否存在
		if(categoryVO.getParentCategoryId() != null && categoryVO.getParentCategoryId() != 0) {
			CsCategories csCategories = getById(categoryVO.getParentCategoryId());
			//如果为null,直接返回
			if(csCategories == null) {
				throw new BizException(ResultCodeEnum.DATA_NOT_FOUND,"父级目录不存在");
			}

			//判断父级目录是否属于当前知识库
			if(!csCategories.getLibraryId().equals(categoryVO.getLibraryId())){
				throw new BizException(ResultCodeEnum.DATA_EXCEPTION,"父级目录不属于当前知识库");
			}
		}else {
			//默认为0
			categoryVO.setParentCategoryId(0L);
		}

		CsCategories convert = CategoryCovert.convert(categoryVO);

		convert.setCreatedAt(new Date());
		convert.setCreatedBy(StpUtil.getLoginIdAsString());

		return R.status(save(convert));
	}

	@Override
	public R<LibraryTreeDTO> queryTreeInfo(String libraryId, String categoryId) {

		// 参数校验
		if (StringUtils.isBlank(libraryId)) {
			throw new BizException(ResultCodeEnum.PARAM_INVALID, "libraryId is blank");
		}
		if (StringUtils.isBlank(categoryId)) {
			log.info("categoryId is blank, querying root category for libraryId: {}", libraryId);
			categoryId = queryRootCategoryId(libraryId);
		}

		// 获取当前节点数据
		CsCategories csCategories = getById(categoryId);
		if (csCategories == null) {
			log.error("Category with categoryId {} not found in libraryId {}", categoryId, libraryId);
			throw new BizException(ResultCodeEnum.DATA_NOT_FOUND, "categoryId is not exist");
		}

		// 获取当前节点的文件和文章数据
		List<FileDTO> fileDTOS = csFileService.listFileByCategoryId(categoryId, libraryId);
		List<ArticleDTO> articleDTOS = csArticleService.listArticleByCategoryId(categoryId, libraryId);

		// 获取当前节点的子节点数据
		List<CsCategories> childCategories = queryChildCategories(categoryId, libraryId);
		if (childCategories.isEmpty()) {
			log.info("No child categories found for categoryId {} in libraryId {}", categoryId, libraryId);
			return R.success(buildLibraryTreeDTO(csCategories, fileDTOS, articleDTOS, List.of()));
		}

		// 转换子节点为 DTO
		List<CategoryNodeDTO> categoryNodeDTOS = childCategories.stream()
				.map(CategoryCovert::convert)
				.toList();

		log.info("Successfully built tree info for categoryId {} in libraryId {}", categoryId, libraryId);
		return R.success(buildLibraryTreeDTO(csCategories, fileDTOS, articleDTOS, categoryNodeDTOS));
	}

	// 提取根节点查询逻辑
	public String queryRootCategoryId(String libraryId) {
		LambdaQueryWrapper<CsCategories> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(CsCategories::getParentCategoryId, 0L)
				.eq(CsCategories::getLibraryId, libraryId)
				.eq(CsCategories::getDeleted, 0);

		List<CsCategories> rootCategories = list(queryWrapper);
		if (CollectionUtil.isEmpty(rootCategories)) {
			log.error("No root category found for libraryId {}", libraryId);
			throw new BizException(ResultCodeEnum.DATA_NOT_FOUND, "根目录不存在");
		}
		if (rootCategories.size() > 1) {
			log.error("Multiple root categories found for libraryId {}", libraryId);
			throw new BizException(ResultCodeEnum.DATA_EXCEPTION, "存在多个根目录，请检查数据一致性");
		}
		return rootCategories.get(0).getId().toString();
	}

	// 提取子节点查询逻辑
	private List<CsCategories> queryChildCategories(String categoryId, String libraryId) {
		LambdaQueryWrapper<CsCategories> query = new LambdaQueryWrapper<>();
		query.eq(CsCategories::getParentCategoryId, categoryId)
				.eq(CsCategories::getLibraryId, libraryId)
				.eq(CsCategories::getDeleted, 0);
		return list(query);
	}


	// 构建LibraryTreeDTO方法
	private LibraryTreeDTO buildLibraryTreeDTO(CsCategories csCategories,
											   List<FileDTO> fileDTOS,
											   List<ArticleDTO> articleDTOS,
											   List<CategoryNodeDTO> categoryNodeDTOS) {
		LibraryTreeDTO libraryTreeDTO = new LibraryTreeDTO();
		libraryTreeDTO.setCategoryId(String.valueOf(csCategories.getId()));
		libraryTreeDTO.setName(csCategories.getTitle());
		libraryTreeDTO.setDescription(csCategories.getDescription());
		libraryTreeDTO.setFileList(fileDTOS);
		libraryTreeDTO.setArticleList(articleDTOS);
		libraryTreeDTO.setChildren(categoryNodeDTOS);
		return libraryTreeDTO;
	}
}




